package com.wetool.service.commodity;

import com.wetool.common.commodity.CommodityResult;
import com.wetool.common.model.Message;
import com.wetool.entity.Category;
import com.wetool.entity.PublicCategory;
import com.wetool.exception.*;
import com.wetool.jpa.CategoryRepo;
import com.wetool.model.CategoryAdd;
import com.wetool.model.CategoryModify;
import com.wetool.model.CategoryTree;
import com.wetool.push.api.model.model.CategoryPushMessage;
import com.wetool.service.CommodityService;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

/**
 * 商家商品分类业务类
 * @author lixin
 */
@Component
public class CategoryService {
	final static int OPT_TYPE_UPDATE = 0;
	final static int OPT_TYPE_DEL = 1;

	@Autowired
	private CategoryRepo categoryRepo;

	@Autowired
	private CommodityService commodityService;
	
	@Autowired
	private PublicCategoryService publicCategoryService;
	
	@Autowired
	private PushService pushService;

	private static final Logger logger = LogManager.getLogger(CategoryService.class); 
	
	/**
	 * 展示商品分类目录下根节点
	 * @param merchantId
	 * @param i
	 * @return
	 * @throws MerchantNotLoginException
	 */
	public Long getRootNode(Long merchantId) throws MerchantNotLoginException{
		if (merchantId == null) {
			logger.debug("商家商品分类业务类(商品分类目录下根节点) -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品分类业务类(商品分类目录下根节点) -> 商家ID为空");
		}
		Long categoryId = categoryRepo.getByMerchantIdAndCategoryLevel(merchantId,0);
		return categoryId;
	}
	
	/**
	 * 商品分类Id是否为子节点
	 * @param categoryId
	 * @return
	 */
	public Boolean getIsLeaf(Long categoryId) {
		return categoryRepo.getIsLeaf(categoryId);
	}
	
	/**
	 * 商品分类
	 * @param merchantId商家Id
	 * @param categoryId商品分类ID
	 * @return 商品分类树结构
	 * @throws MerchantNotLoginException 
	 * @throws CategoryNotFindException 
	 */
	public List<CategoryTree> getTree(Long merchantId, Long categoryId) throws MerchantNotLoginException, CategoryNotFindException {
		if(merchantId == null) {
			logger.debug("商家商品分类业务类(商品分类展示) -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品分类业务类(商品分类展示) -> 商家ID为空");
		}
		if (categoryId == null) {
			logger.debug("商家商品分类业务类(商品分类展示) -> 商品分类不存在");
			throw new CategoryNotFindException("商家商品分类业务类(商品分类展示) -> 商品分类不存在");
		}
		Category root = categoryRepo.findOne(categoryId);//查询商家商品分类节点
		if (root == null) {
			return new ArrayList<>();
		}
		Long parentId = null;
		if (root.getParent() != null) {//当父节点对象不为空，获取父节点ID
			parentId =root.getParent().getId();
		}
		List<CategoryTree> result = new ArrayList<CategoryTree>();
		/* 过滤非商家ID的分类 */
		List<Category> children = categoryRepo.findByParentAndMerchantId(root,merchantId);//获取子节点对象集合
		/* 构造树模型 */
		CategoryTree tree = build(children,
					new CategoryTree(root.getId(), root.getCategoryName(), parentId, root.isLeaf()));// 获取商品分类商品树
		result.add(new CategoryTree(tree.getValue(), tree.getLabel(), tree.getParent(), tree.isLeaf()));
		if (tree.getChildren() != null) {
			result.addAll(tree.getChildren());
		}
		logger.debug("商家商品分类业务类(商品分类展示) . 参数 分类集合【{}】", result);
		return result;
	}

	/**
	 * 构造商品分类树结构 递归构造
	 * @param categorys
	 * @param tree
	 * @return
	 */
	private CategoryTree build(List<Category> categorys, CategoryTree tree) {
		if (categorys != null && categorys.size() > 0) {
			for (Category children : categorys) {
				/* 逻辑删除目录不展示 */
				if (children.isDeleted() == true) {
					continue;
				}
				CategoryTree node = new CategoryTree(children.getId(), children.getCategoryName(), children.getParent().getId(), children.isLeaf());
				if (tree.getChildren() == null) {
					List<CategoryTree> nodes = new ArrayList<CategoryTree>();
					nodes.add(node);
					tree.setChildren(nodes);
				} else {
					tree.getChildren().add(node);
				}
				List<Category> childrens = children.getChildren();
				if (childrens != null && childrens.size() > 0) {
					build(childrens, node);
				}
			}
		}
		return tree;
	}

	/**
	 * 新增商家时将公共分类信息导入商家分类信息
	 * @return List<Category>
	 * @throws MerchantNotLoginException 
	 */
	@Transactional
	public List<Category> saveCategoryByMerchant(Long merchantId) throws MerchantNotLoginException{
		if (merchantId == null) {
			logger.debug("商家商品分类业务类(新增商家时将公共分类信息导入商家分类信息) -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品分类业务类(新增商家时将公共分类信息导入商家分类信息) -> 商家ID为空");
		}
		List<PublicCategory> publicCategorys = publicCategoryService.findAll();//获取公共库分类信息
		for (PublicCategory publicCategory : publicCategorys) {
			if ("全部".equals(publicCategory.getCategoryName())) {
				continue;
			}
			Category category = new Category();
			BeanUtils.copyProperties(publicCategory, category);//数据拷贝
			category.setId(null);//新增ID未null
			category.setChildren(null);//子类设置为null 添加时添加父目录
			category.setMerchantId(merchantId);//设置商家ID
			category = categoryRepo.save(category);//先保存
			if (publicCategory.getParent() != null) {//拷贝数据时判断是否有父目录
				String name = publicCategory.getParent().getCategoryName();
				Category c = null;
				if ("全部".equals(name)) {
					 c = categoryRepo.getByMerchantIdAndlikeCategoryName(-1L,name);
				} else {
					 c = categoryRepo.getByMerchantIdAndlikeCategoryName(merchantId,name);//查找同商家的父目录
				}
				category.setParent(c);//保存
			}else {
				category.setParent(null);
			}
			category = categoryRepo.save(category);
		}
		return null;
	}
	
	/**
	 * 商品分类添加
	 * @param category 添加数据
	 * @return
	 * @throws MerchantNotLoginException 
	 * @throws CategoryNameRepetitionException 
	 */
	public Category add(CategoryAdd category) throws MerchantNotLoginException, CategoryNameRepetitionException {
		if (category.getMerchantId() == null) {
			logger.debug("商家商品分类业务类(商品分类添加) -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品分类业务类(商品分类添加) -> 商家ID为空");
		}
		Long count = categoryRepo.countByName(category.getCategoryName(),category.getMerchantId(),category.getParentId());
		if (count > 0) {
			logger.debug("商家商品分类业务类(商品分类添加) -> 分类名称重复 . 参数分类名称{}", category.getCategoryName());
			throw new CategoryNameRepetitionException("商家商品分类业务类(商品分类添加) -> 分类名称重复"); 	
		}
		Category c = new Category();
		BeanUtils.copyProperties(category, c);//对象属性值复制
		if(c.getCategoryLevel() == null){c.setCategoryLevel(1);}
		c.setParent(categoryRepo.findOne(category.getParentId()));//添加父节点数据
		c = categoryRepo.saveAndFlush(c);
		Boolean flag = pushService.sendCategoryMassage(new CategoryPushMessage(c.getMerchantId(), true));
		logger.info("推送商品分类信息 . 参数 推送是否成功【{}】",flag);
		return c;
	}

	/**
	 * 修改商品分类
	 * @param categoryId 商品分类ID
	 * @param categoryModify 商品修改参数对象
	 * @return Category 商品分类详情
	 * @throws NodeRelationException
	 * @throws ChangeIsLeafException
	 * @throws MerchantNotLoginException 
	 */
	public Category update(Long categoryId, CategoryModify categoryModify) throws Exception {
		if (categoryModify.getMerchantId() == null) {
			logger.debug("商家商品分类业务类(修改商品分类) -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品分类业务类(修改商品分类) -> 商家ID为空");
		}
		Category category = new Category();
		Long count = categoryRepo.countByNameNot(categoryModify.getCategoryName(),categoryModify.getMerchantId(),categoryModify.getParentId(),categoryId);
		if (count > 0) {
			logger.debug("商家商品分类业务类(修改商品分类) -> 分类名称重复 . 参数分类名称{}", categoryModify.getCategoryName());
			throw new CategoryNameRepetitionException("商家商品分类业务类(修改商品分类) -> 分类名称重复"); 	
		}
		BeanUtils.copyProperties(categoryModify, category);
		/* 如果存在parentId存在，则说明正在执行变更父节点操作 */
		if (categoryModify.getParentId() != null) {

			/* 检查当前节点是否存在子节点 */
			Category entity = categoryRepo.findOne(categoryId);

			/* 查询父节点并添加 */
			Category parent = categoryRepo.findOne(categoryModify.getParentId());
			category.setParent(parent);
			if (category.isLeaf() != entity.isLeaf()) {
				logger.debug("商家商品分类业务类(修改商品分类) -> 改变节点类型异常 . 参数：是否为节点【{}】",category.isLeaf());
				throw new ChangeIsLeafException("商家商品分类业务类(修改商品分类) -> 改变节点类型异常"); // 改变节点类型异常
			}
		}
		/* 存入目录ID */
		category.setId(categoryId);
		category = categoryRepo.saveAndFlush(category);
		Boolean flag = pushService.sendCategoryMassage(new CategoryPushMessage(category.getMerchantId(), true));
		logger.info("推送商品分类信息 . 参数 推送是否成功【{}】",flag);
		return category;
	}

	/**删除商品分类（商家库）
	 * 
	 * @param categoryId 商品分类ID
	 * @throws NodeRelationException
	 * @throws DataRelationException
	 */
	public Message<?> delete(Long categoryId) {
		/* 检查当前节点是否存在子节点 */
		Long entity = categoryRepo.findByParentAndIsDeleted(categoryId,false);
		if (entity!= null && entity > 0) {
			logger.debug("商家商品分类业务类(删除商品分类) -> 节点关联异常");
			return new Message<>(CommodityResult.NODERELATION); // 节点关联异常
		}

		/* 检查当前节点是否存在商品数据 */
		Long count = commodityService.countByCategoryId(categoryId);
		if (count > 0) {
			logger.debug("商家商品分类业务类(删除商品分类) -> 数据关联异常");
			return new Message<>(CommodityResult.DATARELATION);
		}
		Category category = categoryRepo.findOne(categoryId);
		category.setDeleted(true);
		categoryRepo.saveAndFlush(category);
		Boolean flag = pushService.sendCategoryMassage(new CategoryPushMessage(category.getMerchantId(), true));
		logger.info("推送商品分类信息 . 参数 推送是否成功【{}】",flag);
		return new Message<>(CommodityResult.SUCCESS);
	}
	
	/**
	 * 获取目录ID（包含子目录ID）
	 * @param merchantId 商家ID
	 * @param categoryId	目录ID
	 * @return 目录ID数组
	 * @throws MerchantNotLoginException 
	 * @throws CategoryNotFindException 
	 */
	public Long[] getIds(Long merchantId, Long categoryId) throws MerchantNotLoginException, CategoryNotFindException {
		if (categoryId == null) {
			categoryId = getRootNode(-1L);
		}
		List<CategoryTree> tree = getTree(merchantId, categoryId);	//目录树结构对象列表
		//取出所有子节点
		for (int i=0;i< tree.size();i++) {
			if (tree.get(i).getChildren() != null) {	
				tree.addAll(tree.get(i).getChildren());
			}
		}
		List<Long> categoryIds = tree.stream()
				//.filter(item -> item.isLeaf() == false)
				.collect(
						() -> new ArrayList<Long>(),
						(list, item) -> list.add(Long.valueOf(item.getValue())),
						(list1, list2) -> list1.addAll(list2)
						);
		return categoryIds.toArray(new Long[categoryIds.size()]);
	}

	/**
	 * 获取目录ID（包含子目录ID）
	 * @param merchantId 商家ID
	 * @param categoryId	目录ID
	 * @return 目录ID数组
	 * @throws MerchantNotLoginException 
	 */
	public Long[] getIds( Long categoryId) throws MerchantNotLoginException {
		List<CategoryTree> tree = getTree(categoryId);	//目录树结构对象列表
		//取出所有子节点
		for (int i=0;i< tree.size();i++) {
			if (tree.get(i).getChildren() != null) {	
				tree.addAll(tree.get(i).getChildren());
			}
		}
		List<Long> categoryIds = tree.stream()
				//.filter(item -> item.isLeaf() == false)
				.collect(
						() -> new ArrayList<Long>(),
						(list, item) -> list.add(Long.valueOf(item.getValue())),
						(list1, list2) -> list1.addAll(list2)
						);
		return categoryIds.toArray(new Long[categoryIds.size()]);
	}
	
	/**
	 * 商品分类
	 * @param merchantId商家Id
	 * @param categoryId商品分类ID
	 * @return 商品分类树结构
	 * @throws MerchantNotLoginException 
	 */
	public List<CategoryTree> getTree( Long categoryId){
		Category root = categoryRepo.findOne(categoryId);//查询商家商品分类节点
		Long parentId = null;
		if (root.getParent() != null) {//当父节点对象不为空，获取父节点ID
			parentId =root.getParent().getId();
		}
		List<CategoryTree> result = new ArrayList<CategoryTree>();
		List<Category> children = root.getChildren();//获取子节点对象集合
		/* 构造树模型 */
		CategoryTree tree = build(children,
				new CategoryTree(root.getId(), root.getCategoryName(), parentId, root.isLeaf()));// 获取商品分类商品树
		result.add(new CategoryTree(tree.getValue(), tree.getLabel(), tree.getParent(), tree.isLeaf()));
		if (tree.getChildren() != null) {
			result.addAll(tree.getChildren());
		}
		return result;
	}

	/**
	 * 多选删除
	 * @param categoryId
	 * @return
	 * @throws NodeRelationException
	 * @throws DataRelationException
	 */
	@Transactional
	public Message<?> deletes(List<Long> categoryId) {
		List<Long> sonIds = new ArrayList<>();
		for (Long id : categoryId) {//查询分类子id集合
			List<Long> ids = categoryRepo.getByPrentId(id);
			sonIds.addAll(ids);
		}
		if (!sonIds.isEmpty()) {//判断父id 是否存在于删除集合中
			for (Long id : sonIds) {
				Boolean flag = categoryId.contains(id);
				if (!flag) {//如果不存在 返回状态码
					return new Message<>(CommodityResult.NODERELATION);
				}
			}
		}
		for (Long id : categoryId) {
			/* 删除所选分类 */
			Message<?> message = this.delete(id);
			if (message.getCode() != 0) {
				return message;
			}
		}
		return new Message<>(CommodityResult.SUCCESS);
	}

	/**
	 * 根据编号查询商品分类id
	 * @param categoryId
	 * @return
	 */
	public String getById(Long categoryId) {
		/* 分类编号获取详情 */
		Category category = categoryRepo.findOne(categoryId);
		if (category == null || category.isDeleted()) {
			return categoryRepo.findOne(1L).getCategoryName();
		}
		return category.getCategoryName();
	}

}
